import { mapGetters } from 'vuex'
export default (app, option = {}) => {
  const mixins = {
    data() {
      return {
        data: [],
        form: {},
        params: {},
        api: require(`@/api/${option.name}`),
        loading: false,
        page: {},
        expandRow: [],
        multipleSelection: [],
        customKey:null
      }
    },
    computed: {
      option() {
        return require(`@/option/${option.name}`).default(this)
        // return require(`@/option/${option.name}`)
        // get(){
        //   return require(`@/option/${option.name}`).default(this)
        // },
        // set(value){

        // }
      },
      bindVal() {
        return {
          ref: 'crud',
          option: this.option,
          data: this.data,
          tableLoading: this.loading,
          permission: this.permissionList
        }
      },
      onEvent() {
        return {
          'on-load': this.getList,
          'row-save': this.rowSave,
          'row-update': this.rowUpdate,
          'row-del': this.rowDel,
          'refresh-change': this.refreshChange,
          'search-reset': this.searchChange,
          'search-change': this.searchChange,
          'expand-change': this.expandChange,
          'selection-change': this.handleSelectionChange
        }
      },
      rowKey() {
        return option.rowKey || this.customKey || 'id'
      },
      rowName() {
        return option.rowName || 'id'
      },
      ...mapGetters(['permission', 'permissions']),
      permissionList() {
        if (!this.permissions) {
          return {
            allBtn: false,
            delBtn: false,
            editBtn: false,
            searchShow: false
          }
        }
        const all_permission = '*:*:*'
        const path = option.name.split('/').join(':')
        if (all_permission === this.permissions.join('')) {
          return {
            allBtn: true,
            delBtn: true,
            editBtn: true,
            searchShow: true
          }
        }
        return {
          // addBtn: this.vaildData(this.permissions[`${path}:add`], false),
          // delBtn: this.vaildData(this.permissions[`${path}:remove`], false),
          // editBtn: this.vaildData(this.permissions[`${path}:edit`], false),
          // searchShow: this.vaildData(this.permissions[`${path}:query`], false)
          addBtn: this.permissions.includes(`${path}:add`),
          delBtn: this.permissions.includes(`${path}:remove`),
          editBtn: this.permissions.includes(`${path}:edit`),
          searchShow: this.permissions.includes(`${path}:query`)
        }
      }
    },
    methods: {
      expandChange(row, isExpand) {
        const index = this.expandRow.findIndex(
          item => item[this.option.rowKey] === row[[this.option.rowKey]]
        )
        if (isExpand) {
          if (index === -1) {
            this.expandRow.push(row)
          }
        } else {
          if (index !== -1) {
            this.expandRow.splice(index, 1)
          }
        }
      },
      getList() {
        const callback = () => {
          let { sendData } = beforeCallback()
          this.api[option.list || 'list'](sendData).then(res => {
            afterCallback(res)
          })
        }
        const beforeCallback = () => {
          this.loading = true
          const pageParams = {}
          pageParams[option.pageNumber || 'pageNum'] = this.page.currentPage
          pageParams[option.pageSize || 'pageSize'] = this.page.pageSize
          const data = Object.assign(pageParams, this.params, this.$route.query)
          if (this.isResetDataEmpty === undefined) {
            this.data = []
          }
          const sendData = {}
          for (const key in data) {
            if (
              !(data[key] === '') &&
              !(data[key] === undefined) &&
              !(data[key] === null)
            ) {
              sendData[key] = data[key]
            }
          }
          return {
            sendData
          }
        }

        const afterCallback = (res) => {
          this.loading = false
          let data
          if (option.res) {
            data = option.res(res)
          } else {
            data = res
          }
          this.page.total = data[option.total || 'total']
          const result = data[option.data || 'data']
          if (this.listAfter) {
            this.listAfter(result)
          } else {
            this.data = result
          }
          this.$nextTick(() => {
            if (this.expandRow.length) {
              this.expandRow.forEach(item => {
                this.$refs.crud.toggleRowExpansion(item)
              })
            }
          })
        }


        if (this.resetList) {
          new Promise(resolve => {
            return this.resetList(resolve)
          }).then((res) => {
            beforeCallback()
            afterCallback(res)
          })
        } else if (this.listBefore) {
          new Promise(resolve => {
            return this.listBefore(resolve)
          }).then(() => {
            callback()
          })
        } else {
          callback()
        }
      },
      rowSave(row, done, loading) {
        const callback = (sendData) => {
          delete this.form.params
          this.api[option.add || 'add'](sendData || row)
            .then(data => {
              if (data.code === 200) {
                this.getList()
                if (this.addAfter) {
                  this.addAfter(data)
                } else {
                  this.$message.success('新增成功')
                }
                done()
              } else {
                this.$message.error(data.msg)
                loading()
              }
            })
            .catch(() => {
              loading()
            })
        }
        if (this.addBefore) {
          return this.addBefore(callback, row)
        }
        callback()
      },
      rowUpdate(row, index, done, loading) {
        const callback = () => {
          delete this.form.params
          // this.api[option.update || 'update'](row[this.rowKey], this.form, index).then((data) => {
          this.api[option.update || 'update'](this.form)
            .then(data => {
              if (data.code === 200) {
                this.getList()
                if (this.updateAfter) {
                  this.updateAfter(data)
                } else {
                  this.$message.success('更新成功')
                }
                done()
              } else {
                this.$message.error(data.msg)
                loading()
              }
            })
            .catch(() => {
              loading()
            })
        }
        if (this.updateRowBefore) {
          this.updateRowBefore()
        }
        callback()
      },
      rowDel(row, index, loading) {
        const callback = () => {
          let ids = row[this.rowKey]
          if (this.multipleSelection.length > 1) {
            ids = this.multipleSelection.map(item => item[this.rowKey]).join()
          }
          this.api[option.del || 'del'](ids, row, this.params).then(data => {
            if (data.code === 200) {
              this.getList()
              if (this.delAfter) {
                this.delAfter(data, row, index)
              } else {
                this.$message.success('删除成功')
              }
            } else {
              this.$message.error(data.msg)
              loading()
            }
          })
        }
        if (this.delBefore) {
          this.delBefore(row, callback)
        } else {
          this.$confirm(`确定要操作此条数据吗?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            callback()
          })
        }
      },
      searchChange(params, done) {
        if (done) done()

        if (this.searchChangBefore) {
          this.params = {}
          this.searchChangBefore(params)
        } else {
          this.params = params
        }
        this.page.currentPage = 1
        this.getList()
      },
      refreshChange() {
        this.getList()
      },
      handleSelectionChange(val) {
        this.multipleSelection = val
      }
    }
  }
  app.mixins = app.mixins || []
  app.mixins.push(mixins)
  return app
}
